#include "SimpleBgSubModel.h"

SimpleBgSubModel::SimpleBgSubModel()
{
	m_frameCount = 0;
	m_width = 0;
	m_height = 0;
	m_highFrame = Mat::zeros(m_height, m_width, CV_32FC3);
	m_lowFrame = Mat::zeros(m_height, m_width, CV_32FC3);
}

SimpleBgSubModel::~SimpleBgSubModel()
{

}

void SimpleBgSubModel::AccumulateBackground(const Mat &frame)
{
	Mat extFrame(frame.rows, frame.cols, CV_32FC3);
	Mat diffFrame(frame.rows, frame.cols, CV_32FC3);
	frame.convertTo(extFrame, CV_32FC3);
	if(0 == m_frameCount)
	{
		m_width = frame.cols;
		m_height = frame.rows;
		//m_avgFrame.create(m_height, m_width, CV_32FC3);
		m_preFrame.create(m_height, m_width, CV_32FC3);
		//m_diffFrame.create(m_height, m_width, CV_32FC3);
		m_avgFrame = Mat::zeros(m_height, m_width, CV_32FC3);
		m_diffFrame = Mat::zeros(m_height, m_width, CV_32FC3);
		extFrame.copyTo(m_preFrame);
	}
	if(m_width != frame.cols || m_height != frame.rows)
	{
		cout<<"Please ensure the frames have same width and height!"<<endl;
		return ;
	}
	else
	{
		accumulate(extFrame, m_avgFrame);
		absdiff(extFrame, m_preFrame, diffFrame);
		accumulate(diffFrame, m_diffFrame);
		extFrame.copyTo(m_preFrame);
		m_frameCount++;
	}
	//imshow("pre", m_preFrame);
	//'imshow("ext", frame);
}

void SimpleBgSubModel::ScaleHigh(const float &scale)
{
	Mat scaleDiff(m_height, m_width, CV_32FC3);
	m_diffFrame.convertTo(scaleDiff, CV_32FC3, scale);
	add(m_avgFrame, scaleDiff, m_highFrame);
}

void SimpleBgSubModel::ScaleLow(const float &scale)
{
	Mat scaleDiff(m_height, m_width, CV_32FC3);
	m_diffFrame.convertTo(scaleDiff, CV_32FC3, scale);
	subtract(m_avgFrame, scaleDiff, m_lowFrame);
}

void SimpleBgSubModel::CreateModel(/*Mat *frames, const int &frameCount, */const float &scaleHigh, const float &scaleLow)
{
	/*for(int i = 0; i < frameCount; i++)
	{
		AccumulateBackground(frames[i]);
	}*/
	m_avgFrame.convertTo(m_avgFrame, CV_32FC3, (float)(1.0 / m_frameCount));
	m_diffFrame.convertTo(m_diffFrame, CV_32FC3, (float)(1.0 / m_frameCount));
	add(m_diffFrame, Scalar(1.0, 1.0, 1.0), m_diffFrame);
	ScaleHigh(scaleHigh);
	ScaleLow(scaleLow);
}

void SimpleBgSubModel::BackgroundDiff(const Mat &img, Mat &mask)
{
	if(m_height != img.rows || m_width != img.cols)
	{
		cout<<"Please ensure the frames have the same width and height!"<<endl;
		return ;
	}
	Mat extImg(m_height, m_width, CV_32FC3);
	img.convertTo(extImg, CV_32FC3);
	Mat *grayImg = new Mat[3];
	Mat *highFrame = new Mat[3];
	Mat *lowFrame = new Mat[3];
	for(int i = 0; i < 3; i++)
	{
		grayImg[i].create(m_height, m_width, CV_32FC1);
		highFrame[i].create(m_height, m_width, CV_32FC1);
		lowFrame[i].create(m_height, m_width, CV_32FC1);
	}
	split(extImg, grayImg);
	split(m_highFrame, highFrame);
	split(m_lowFrame, lowFrame);

	Mat tmpMask(m_height, m_width, CV_8UC1);
	inRange(grayImg[0], lowFrame[0], highFrame[0], mask);
	inRange(grayImg[1], lowFrame[1], highFrame[1], tmpMask);
	bitwise_or(mask, tmpMask, mask);
	inRange(grayImg[2], lowFrame[2], highFrame[2], tmpMask);
	bitwise_or(mask, tmpMask, mask);
	subtract(Scalar(255), mask, mask);

/*	Mat hiF(m_height, m_width, CV_8UC3);
	highFrame[0].convertTo(hiF, CV_8UC3);
	imshow("h0", hiF);
	imshow("h1", highFrame[1]);
	imshow("h2", highFrame[2]);
	imshow("l0", lowFrame[0]);
	imshow("l1", lowFrame[1]);
	imshow("l2", lowFrame[2]);
*/	delete[] grayImg;
	delete[] highFrame;
	delete[] lowFrame;
}